home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / ELECTRON / 0989.ZIP / ESPRESSO.ARC / MEMORY.C < prev    next >
Text File  |  1987-03-13  |  4KB  |  113 lines

  1. /*
  2.     module: memory.c 
  3.     purpose: Efficient memory management scheme for large blocks of memory
  4. */
  5. #include "espresso.h"
  6.  
  7. #ifdef UNIX
  8. #define malloc(n) sbrk((int)n)
  9. #endif
  10.  
  11. char *malloc();
  12.  
  13. #define BINS 64
  14. union memory_block {
  15.     union memory_block *nextblock;      /* Pointer to next block on chain */
  16.     int binnum;                         /* remember bin number */
  17. } *binptr[BINS];
  18. static int num_alloc[BINS], num_active[BINS], alloc_size; 
  19.  
  20.  
  21. /* mem_stats -- report memory usage statistics */
  22. void mem_stats()
  23. {
  24.     register int i, size, active_bytes = 0, alloc_bytes = 0;
  25.     for(i = BINS-1; i >= 0; i--) {
  26.         size = (i % 2 == 0 ? 3 : 4) << (i/2 - 2);
  27.         alloc_bytes += num_alloc[i] * size;
  28.         active_bytes += num_active[i] * size;
  29.     }
  30.     active_bytes = (int) (active_bytes / 1024.0 + 0.5);
  31.     alloc_bytes = (int) (alloc_bytes / 1024.0 + 0.5);
  32.     printf("# %dK bytes active out of %dK bytes allocated\n",
  33.         active_bytes, alloc_bytes);
  34. }
  35.  
  36. /*
  37.     mem_alloc -- allocate an array of "num" objects each of size "size".  Also
  38.     return the actual number of array elements allocated
  39. */
  40. char *mem_alloc(num, size, actual)
  41. int num, size, *actual;
  42. {
  43.     char *p = alloc(num*size);
  44.     *actual = (int) (alloc_size - sizeof(union memory_block)) / size;
  45.     return p;
  46. }
  47. /* alloc -- efficiently allocate a (large) array of elements */
  48. char *alloc(bytes)
  49. int bytes;
  50. {
  51.     register int log, index, n, request=bytes+sizeof(union memory_block *);
  52.     register union memory_block *p;
  53.  
  54.     if( bytes < 0 ) {
  55.       printf("Espresso unable to allocate adequate memory in DOS or XENIX\n");
  56.       printf("Exiting to OS\n");
  57.       exit(-1);
  58.       }
  59.   
  60.     /* compute log such that 2**log >= request */
  61.     for(n = request-1, log = 1; (n >>= 1) > 0; log++)
  62.         ;
  63.     log -= 2;
  64.     /* determine the bin number and actual alloc size (based on the log) */
  65.     if (request <= (3 << log))
  66.         index = log*2, alloc_size = 3 << log;
  67.     else
  68.         index = log*2 + 1, alloc_size = 4 << log;
  69.     /* See if we have a free block in the garbage list for this bin */
  70.     if ((p = binptr[index]) == NULL) {
  71.         /* Must allocate a new block -- no free space in garbage list */
  72.         p = (union memory_block *) malloc((unsigned) alloc_size);
  73.         if (p == NULL) {
  74.             /* Check if a larger and free block exists */
  75.             for(n = index+1, index = 0; n < BINS; n++)
  76.                 if (binptr[n] != NULL) {
  77.                     index=n; p=binptr[index]; binptr[index]=p->nextblock;
  78.                     break;
  79.                 }
  80.             if (index == 0) {
  81.                 fprintf(stderr, "espresso: failed allocating %d (%d) bytes\n",
  82.                     request, alloc_size);
  83.                 exit(-1);
  84.             }
  85.         }
  86.         num_alloc[index]++;
  87.     } else
  88.         /* We can reuse the first entry on the garbage list for this size */
  89.         binptr[index] = p->nextblock;
  90.     num_active[index]++;
  91.     p->binnum = index | 0x5500;
  92.     return( (char *) (p+1) );
  93. }
  94.  
  95. /* mem_free -- free the memory allocated */
  96. void mem_free(block)
  97. char *block;
  98. {
  99.     register union memory_block *p = (union memory_block *) block - 1;
  100.     register int index = p->binnum;
  101.  
  102.     if (((index & 0xFF00) != 0x5500) || ((index &= 0x00FF) >= BINS)) {
  103.         fprintf(stderr, "%s: corrupt pointer returned, addr=%x, index=%x\n",
  104.             "memory.c/mem_free", p, index);
  105.         exit(-1);
  106.     }
  107.  
  108.     /* Link p into the garbage list for this block size */
  109.     p->nextblock = binptr[index];
  110.     binptr[index] = p;
  111.     num_active[index]--;
  112. }
  113.